package parser

import "strings"

type JsonListener struct {
	builder   strings.Builder
	pretty    bool
	scope     int
	lineStart bool
}

const (
	Empty   = ' '
	NewLine = '\n'
)

func (listener *JsonListener) GetValue() string {
	return listener.builder.String()
}

func (listener *JsonListener) newLine() {
	if !listener.pretty {
		return
	}
	listener.lineStart = true
	listener.builder.WriteByte(NewLine)
}

func (listener *JsonListener) padding() {
	if !listener.pretty {
		return
	}
	if listener.lineStart {
		currentIndent := listener.scope * 4
		for i := 0; i < currentIndent; i++ {
			listener.builder.WriteByte(Empty)
		}
	}
}

func (listener *JsonListener) enterScope() {
	listener.scope++
}
func (listener *JsonListener) exitScope() {
	listener.scope--
}

func (listener *JsonListener) append(value string) {
	listener.padding()
	listener.builder.WriteString(value)
	listener.lineStart = false
}

func (listener *JsonListener) EnterNumberNode(lexer *Lexer) {
	listener.append(lexer.value)
}
func (listener *JsonListener) EnterStringNode(lexer *Lexer) {
	listener.append("\"" + lexer.value + "\"")
}
func (listener *JsonListener) EnterNullNode(lexer *Lexer) {
	listener.append(lexer.value)
}
func (listener *JsonListener) EnterBoolNode(lexer *Lexer) {
	listener.append(lexer.value)
}
func (listener *JsonListener) EnterCommentNode(lexer *Lexer) {
	listener.append("//" + lexer.value)
}
func (listener *JsonListener) EnterObjectNode(*Lexer) {
	listener.append("{")
	listener.newLine()
	listener.enterScope()
}
func (listener *JsonListener) ExitObjectNode(*Lexer) {
	listener.exitScope()
	listener.newLine()
	listener.append("}")
}
func (listener *JsonListener) EnterArrayNode(*Lexer) {
	listener.append("[")
	listener.newLine()
	listener.enterScope()
}
func (listener *JsonListener) ExitArrayNode(*Lexer) {
	listener.exitScope()
	listener.newLine()
	listener.append("]")
}
func (listener *JsonListener) EnterCommaNode(*Lexer) {
	listener.append(",")
	listener.newLine()
}
func (listener *JsonListener) EnterColonNode(*Lexer) {
	listener.append(":")
}
